home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / games / lorri4.zip / CONTROL.SCR < prev    next >
Text File  |  1995-09-24  |  56KB  |  1,886 lines

  1. !
  2. ! CONTROL.SCR
  3. !
  4. ! This script manages some independent functions of the game system.  The
  5. ! script is called by the game driver at certain points during game play,
  6. ! and the entry points are numeric (@0, @1, @2..) instead of the usual entry
  7. ! points (@TALK, @GET, ..).
  8. !
  9. ! QUICK SUMMARY OF ENTRY POINTS:
  10. !
  11. ! :@0 - Time Control.         Executed once every minute of game time.
  12. !                             (See 'MOVES_PER_MINUTE' parameter)
  13. !
  14. ! :@1 - PLAYER MOVES          Invoked for each PLAYER during a FIGHT
  15. !
  16. ! :@2 - MONSTER MOVES         Invoked once to move every monster at
  17. !                             once during a fight (not once for each
  18. !                             monster)
  19. !
  20. ! :@3 - Keyboard/Mouse Event. Called every time a KEY is pressed or a mouse
  21. !                             button clicked during normal game play.
  22. !
  23. ! :@4 - POSITION MONSTER      Invoked once to position the NPCs for
  24. !                             a fight before MONSTER MOVES is called
  25. !                             for the first time.
  26. !
  27. !---------------------------------------------------------------------------!
  28. :@0 ! Entry Point @0 : Time Control Script                                  !
  29. !---------------------------------------------------------------------------!
  30. !
  31. ! This script will start execution at this label once per 'minute' during
  32. ! regular play.  The variable GROUP.MOVES contains the total number of
  33. ! moves the party has made since the begining of the game.  A minute is
  34. ! defined by the current value of the variable 'MovesPerMinute'
  35. !
  36. ! Time is controled by seting the following variables from any script:
  37. !
  38. !   Variable             Default  Description
  39. !   -------------------  -------  --------------------------------
  40. !   MovesPerMinute             2  # of moves per game 'minute'
  41. !   MinutesInAnHour           60  # of minutes in an game 'hour'
  42. !   HoursInADay               24  # of hour in a game 'day'
  43. !   DaysInAMonth              30  # of days in a game 'month'
  44. !   MonthsInAYear             12  # of months in a game 'year'
  45. !   
  46. ! The CURRENT time is obtained (and modified) by setting the following
  47. ! variables:
  48. !
  49. !   year                 Current Year   (Range -32767 to 32767)
  50. !   month                Current Month  (Range 0 to MonthsInAYear - 1)
  51. !   day                  Current Day    (Range 0 to DaysInAMonth  - 1)
  52. !   hour                 Current Hour   (Range 0 to HoursInADay   - 1)
  53. !   minute               Current Minute (Range 0 to MinutesInADay - 1)
  54. !
  55.  
  56. ! Update the clock, one more minute has passed !
  57.   gosub CLOCK_TICK;
  58.  
  59. ! No perform some time dependent actions
  60. ! First, save our original status just in case we need it later..
  61.   L255 = group.current; ! Save current party spokesperson   !
  62.   L254 = FALSE;         ! Have NOT created a random monster !
  63.  
  64. ! THINGS TO DO EVERY MINUTE  
  65.   if group.energy > 0 then
  66.     dec( group.energy );
  67.     ! In the desert, during the day, you consume energy twice as fast
  68.     if world.density(L0,L1) = DESERT and group.vehicle.count = 0 then
  69.       if hour > sunrise and hour < sunset then
  70.         dec( group.energy );
  71.       endif;
  72.     endif;
  73.     if L2 = SWAMP and group.vehicle.count = 0 then 
  74.       if random(5) = 0 then ! one out of 5 !
  75.         L255 = group.current;
  76.         foreach player do
  77.           if not player.poisoned then
  78.             player.poisoned = (random(3) = 0); ! one out of 3 !
  79.             if player.poisoned then
  80.               writeln( player.name, " got poisoned by swamp gas!" );
  81.             endif;
  82.           endif;
  83.         endfor;
  84.         group.current = L255; ! Restore the current spokesperson !
  85.       endif;
  86.     endif;
  87.   endif;
  88.   
  89. ! THINGS TO DO ONCE AN HOUR
  90. if minute = 0 then 
  91. ! !
  92. ! ! We COULD switch landscaping on sunrise/sunset
  93. ! !
  94.   L1 = HoursInADay / 2; ! Noon !
  95.   if hour > L1 then
  96.     writeln( "It's ", hour - L1, "pm" );
  97.   else
  98.     writeln( "It's ", hour, "am" );
  99.   endif;
  100.   ! 
  101.   ! If we wanted to create a "daylight"/"night-type" effect, we have
  102.   ! two options. One, create two landscape sets that are identical
  103.   ! except one uses darker colors (you really need 256 colors for 
  104.   ! this), as follows:
  105.   ! if world.type = OUTDOORS then
  106.   !   if hour = sunrise then
  107.   !     world.landscape = 0;
  108.   !   elsif hour = sunset then
  109.   !     world.landscape = 1;
  110.   !   endif;
  111.   ! endif;
  112.   ! The second one is to have a second PALETTE of colors, which
  113.   ! are darker than the standard palette.  You can then just
  114.   ! change the palette
  115.   !   if hours = sunset then loadpalette( "NIGHT.PAL" );
  116.   !   elsif hour = sunrise then loadpalette( "DAY.PAL" );
  117.   ! Note that 'loadpalette' is not currently available!
  118.  
  119.   ! Create a random monster 1 out of every 5 times (approx) !
  120.   if random(5) = 0 then
  121.     if world.type = OUTDOORS or world.type = DUNGEON or world.type = HAUNTED then
  122.       gosub NEWMONSTER;
  123.     endif;
  124.   endif;
  125.  
  126.   ! Check to see if you have food.. !
  127.   if group.food <= group.size then
  128.     if group.food = 0 then
  129.       writeln( "You have no food.." );
  130.     else
  131.       writeln( "You are running out of food.." );
  132.     endif;
  133.   endif;
  134. endif;
  135.  
  136. ! Every quarter of an hour !
  137. L25 = max(MinutesInAnHour / 4 + 1,2);
  138. if minute % L25 = 0 then
  139.   ! Group must rest within 2 hours or start suffering damage !
  140.   if group.energy < MinutesInAnHour * 2 then 
  141.     if group.energy > 0 then
  142.       writeln( "You must rest soon.." );
  143.     else
  144.       writeln( "You are exhausted.." );
  145.     endif;
  146.   endif;
  147.   ! Check for poison, hunger and exhaustion !
  148.   foreach player do
  149.     if player.hp > 0 then
  150.       if player.poisoned then
  151.         s0 = "poisoning";
  152.         gosub HITPLAYER;
  153.       elsif player.energy = 0 and group.food = 0 then
  154.         s0 = "hunger";
  155.         gosub HITPLAYER;
  156.       elsif group.energy <= 0 then
  157.         s0 = "exhaustion";
  158.         gosub HITPLAYER;
  159.       endif;
  160.     endif;
  161.   endfor;
  162. endif;
  163.  
  164. !
  165. ! The following controls healing and recovery of power.  You can
  166. ! change the rate of healing by using a different value, but remember
  167. ! that the power heal value (8 below) should be a MULTIPLE of the
  168. ! first number (4) or it will not work.
  169. !
  170. if minute % 4 = 0 and group.energy > 0 then
  171.   foreach player do
  172.     if group.food or player.energy then
  173.       gosub HEAL_HP;
  174.       ! Every 8 (twice as slow) restore power
  175.       if minute % 8 = 0 then
  176.         gosub HEAL_PWR;
  177.       endif;
  178.     endif;
  179.   endfor;
  180. endif;
  181.  
  182. ! Go back with same selected spokesperson.. !
  183. group.current = L255;
  184. CONTINUE;
  185.  
  186. !---------------------------------------------------------------------------!
  187. :@1 ! PLAYER MOVES DURING A FIGHT
  188. !---------------------------------------------------------------------------!
  189. !
  190.   frame(player.x,player.y,SYS_FRAME);
  191.   write( player.name, " - " );
  192.   if player.hp < 2 then
  193.     if player.hp = 1 then writeln( "is unconscious!" );
  194.                      else writeln( "is dead!" ); 
  195.     endif;
  196.   elsif player.paralyzed then 
  197.     writeln( "is paralyzed!" );
  198.   elsif player.scared then
  199.     writeln( "is scared!" );
  200.   else
  201.     stats(player);
  202.     keypress = GET_ACTION;
  203.     frame(player.x,player.y,-SYS_FRAME);
  204.     goto :@3;
  205.   endif;
  206.   frame(player.x,player.y,-SYS_FRAME);
  207.   STOP;
  208.  
  209. !---------------------------------------------------------------------------!
  210. :@2 ! Move NPCs during a fight
  211. !---------------------------------------------------------------------------!
  212.   runscript( "FIGHTING", 1 );
  213.   stop;
  214.  
  215. !---------------------------------------------------------------------------!
  216. :@4 ! Position NPCs before a fight
  217. !---------------------------------------------------------------------------!
  218.   runscript( "FIGHTING", 0 );
  219.   stop;
  220.  
  221. !---------------------------------------------------------------------------!
  222. :@3 ! Keyboard Map Entry Point : Process a key press
  223. !---------------------------------------------------------------------------!
  224.  
  225. !
  226. ! THE FOLLOWING TABLE IS A SHORT LIST OF THE VALUES ASSOCIATED WITH EACH
  227. ! KEY. NOTE THAT SPECIAL KEYS HAVE BEEN MAPPED TO DISTINCT NUMBERS TO 
  228. ! AVOID USING THE WIERD PC KEY VALUES.
  229.  
  230. ! CTRL +A to Z    =   1 to  26
  231. ! ESCape key      =  27
  232. ! space           =  32
  233. ! 0-9             =  48 to  57
  234. ! A-Z             =  65 to  90 
  235. ! a-z             =  65 to  90 (i.e. NO LOWERCASE)
  236. ! F1 - F10        = 131 to 140
  237. ! Shift+F1 - F10  = 141 to 150
  238. ! Ctrl +F1 - F10  = 151 to 160
  239. ! ALT  +F1 - F10  = 161 to 170
  240. ! ALT  +1 to 10   = 171 to 180
  241. ! ALT  +A to Z    = 201 to 226
  242. !
  243. ! KEY PAD VALUES (arrow keys!):
  244. ! HOME            = 190        ! CTRL + HOME     = 187
  245. ! END             = 191        ! CTRL + END      = 186
  246. ! UP              = 192        ! CTRL + UP       = 230
  247. ! DOWN            = 193        ! CTRL + DOWN     = 231
  248. ! LEFT            = 194        ! CTRL + LEFT     = 184
  249. ! RIGHT           = 195        ! CTRL + RIGHT    = 185
  250. ! PGUP            = 196        ! CTRL + PGUP     = 189
  251. ! PGDN            = 197        ! CTRL + PGDN     = 188 
  252. ! INS             = 198
  253. ! DEL             = 199
  254. !
  255. ! When you use the mouse to click on something, the variable BUTTON
  256. ! contains which button you clicked (1=Left, 2=Right, 3=Middle), and
  257. ! the rest of the information is obtained as follos:
  258. !
  259. ! VALUE OF KEYPRESS Value of POINTX      Value of POINTY
  260. ! ----------------- ------------------   ------------------
  261. ! VIEW_CLICK 235    World X coordinate   World Y coordinate
  262. ! MENU_CLICK 236    Menu Offset          Menu Choice (0 to n)
  263. ! ICON_CLICK 237    0-7 icon position    0-n block # in blocks file
  264. ! STAT_CLICK 238    6 (group was shown)  Member selected 1-6
  265. !                   0-5 (member shown)   Clicked Item:
  266. !                                        0 = no particular place
  267. !                                        1 = worn weapon location
  268. !                                        2 = worn shield location
  269. !                                        3 = worn armor  location
  270. !                                        4 = worn staff  location
  271. !                                        5 = worn ring   location
  272. !                                        6 = worn amulet location
  273. !                                        7 = Item #  1 in backpack
  274. !                                        8 = Item #  2 in backpack
  275. !                                          .... 
  276. !                                       22 = Item # 16 in backpack
  277. !
  278.   if KEYPRESS = 27 then
  279.     if fighting then
  280.       writeln( "Trying to escape.." );
  281.       fight( STOP );
  282.     endif;
  283.   endif;
  284.   if KEYPRESS >= 65 and KEYPRESS <= 90 then
  285.     on KEYPRESS - 65 goto 
  286.       LETTER_A, LETTER_B, LETTER_C, LETTER_D, LETTER_E,
  287.       LETTER_F, LETTER_G, LETTER_H, LETTER_I, LETTER_J,
  288.       LETTER_K, LETTER_L, LETTER_M, LETTER_N, LETTER_O,
  289.       LETTER_P, LETTER_Q, LETTER_R, LETTER_S, LETTER_T,
  290.       LETTER_U, LETTER_V, LETTER_W, LETTER_X, LETTER_Y, LETTER_Z;
  291.   endif;
  292.   if KEYPRESS >= 48 and KEYPRESS <= 57 then
  293.     on KEYPRESS - 48 goto
  294.       DIGIT_0, DIGIT_1, DIGIT_2, DIGIT_3, DIGIT_4,
  295.       DIGIT_5, DIGIT_6, DIGIT_7, DIGIT_8, DIGIT_9;
  296.   endif;
  297.   if KEYPRESS = 32 goto SPACE;
  298.   ! KEYPAD ARROWS !
  299.   if KEYPRESS >= 190 and KEYPRESS <= 197 then
  300.     on KEYPRESS - 190 goto
  301.      MOVE_UL, MOVE_DL, MOVE_UP, MOVE_DN, MOVE_LF, MOVE_RT, MOVE_UR, MOVE_DR;
  302.   endif;
  303.   if KEYPRESS >= 235 and KEYPRESS <= 240 then
  304.     on KEYPRESS - 235 goto
  305.        VIEW_CLICK, MENU_CLICK, ICON_CLICK, STAT_CLICK;
  306.   endif;
  307.   ! F1 - F10        = 131 to 140
  308.   if keypress >= 131 and keypress <= 140 then
  309.     on keypress - 131 goto FKEY1,FKEY2,FKEY3,FKEY4,FKEY5,FKEY6,FKEY7,FKEY8,FKEY9,FKEY10;
  310.   endif;
  311.  
  312.   ! Not handled by the script. The driver takes the default action !
  313.   CONTINUE;
  314.  
  315. :DIGIT_0
  316.   STATS(-2); ! Display GROUP statistics !
  317.   STOP;
  318.  
  319. :DIGIT_1 :DIGIT_2 :DIGIT_3 :DIGIT_4 :DIGIT_5 :DIGIT_6
  320.   GROUP.CURRENT = KEYPRESS - 49; ! Use 0 to 5 instead of 1 to 6  !
  321.   STATS( GROUP.CURRENT );        ! Display INDIVIDUAL statistics !
  322.   STOP;
  323.  
  324. :DIGIT_7
  325.   STOP;
  326.  
  327. :DIGIT_8
  328.   STOP;
  329.  
  330. :DIGIT_9
  331.   STOP;
  332.  
  333. :LETTER_A
  334.   write( "Attack: " );
  335.   L3 = locate;
  336.   if failure then
  337.     goto NOTHING;
  338.   endif;
  339.   if npc.count then ! Attack a character !
  340.     writeln( npc.class );
  341.     if fighting then
  342.       goto ATTACK_NPC; ! if we ARE fighting, go do it.. !
  343.     else
  344.       if npc.type <> HOSTILE then
  345.         writeln( "Find some bad guys to fight!" );
  346.         STOP;
  347.       endif;
  348.     endif;
  349.     FIGHT; ! START FIGHT MODE. SCRIPT EXECUTION ENDS HERE !
  350.   endif;
  351.   if object.count then
  352.     if object.type = CHEST then
  353.       if object.locktype then
  354.         writeln( "Instead of fighting it, try 'UNLOCK'!" );
  355.       else
  356.         writeln( "It's not even locked, why fight it?" );
  357.       endif;
  358.     else
  359.       writeln( "Why would you want to fight the ", object.name );
  360.     endif;
  361.   endif;
  362.   STOP;
  363.  
  364. :LETTER_B
  365.   STOP;
  366.  
  367. !------------------------------------------------------------------------!
  368. :LETTER_C  ! CAMP OUT !
  369. !
  370. ! First, all temporary magical effects are eliminated by reducing any 
  371. ! attribute that exceeds the maximum value for the same attribute.
  372. !
  373. ! Armor, Shields, Rings and Amulets re-apply their effect (if any).
  374. !
  375. ! The group rests for a third of a day, in one hour increments.  For
  376. ! each hour rested, the group gains 4 hours of 'wake-up' energy.  This
  377. ! means the group should be able to go one and a third days without 
  378. ! sleep.
  379. !
  380. ! Random monsters may appear, but not too often.
  381. !
  382.   if fighting then
  383.     writeln( "This is not a good time to rest.." );
  384.     stop;
  385.   endif;
  386.   frame( group.x, group.y, 10 ); ! ZZZZ.... !
  387.   write( "Resting" );
  388.   voice( "snore", 1000 );
  389.   L255 = group.current; ! Save current party spokesperson   !
  390.   L254 = FALSE;         ! Have NOT created a random monster !
  391.   foreach player do
  392.     gosub NEW_LEVEL; ! Figure out if character went up one level !
  393.     write(".");
  394.     ! First, get rid of temporary magical increases in attributes !
  395.     player.str = min(player.str,player.mstr);
  396.     player.aim = min(player.aim,player.maim);
  397.     player.dex = min(player.dex,player.mdex);
  398.     player.spd = min(player.spd,player.mspd);
  399.     player.pwr = min(player.pwr,player.mpwr);
  400.     player.hp  = min(player.hp, player.mhp);
  401.     player.iq  = min(player.iq, player.miq);
  402.     player.ac  = min(player.ac, player.mac);
  403.     if player.armor.count or player.shield.count then
  404.       if player.armor.cursed or player.shield.cursed then
  405.         player.ac = 0;
  406.       else
  407.         inc( player.ac, player.armor.ac + player.shield.ac );
  408.       endif;
  409.     endif;
  410.     if player.ring.count and player.ring.charges then
  411.       curritem = player.ring;
  412.       gosub M1_INVOKE;
  413.     endif;
  414.     if player.amulet.count and player.amulet.charges then
  415.       curritem = player.amulet;
  416.       gosub M1_INVOKE;
  417.     endif;
  418.   endfor;
  419.   ! # of hours to rest is one third of a day !
  420.   for L253 = 1 to HoursInADay / 3 + 1 do 
  421.     write(".");
  422.     ! Each hour of sleep gives 4 hours of energy !
  423.     if group.energy + MinutesInAnHour * 4 > 32767 then
  424.       group.energy = 32767;
  425.     else
  426.       inc( group.energy, MinutesInAnHour * 4 );
  427.     endif;
  428.     for L252 = 0 to MinutesInAnHour / 2 do
  429.       foreach player do
  430.        if group.food or player.energy then
  431.           gosub HEAL_HP;
  432.           if L252 % 2 then
  433.             gosub HEAL_PWR;
  434.           endif;
  435.         endif;
  436.       endfor;
  437.     endfor;
  438.     ! Check to see if random monsters appear !
  439.     if world.type = OUTDOORS or world.type = DUNGEON or world.type = HAUNTED then
  440.       if random(17) = 0 then
  441.         gosub NEWMONSTER;
  442.         if L254 then
  443.           frame( group.x, group.y, -1 ); ! Restore !
  444.           writeln( "You wake up under attack.." );
  445.           FIGHT;       ! Wake up and fight.. !
  446.         endif;
  447.       endif;
  448.     endif;
  449.   endfor;
  450.   group.current = L255; ! Go back to original spokes person !
  451.   frame( group.x, group.y, -1 ); ! Restore !
  452.   voice( "CHIMES", 1000 );
  453.   writeln( " Done." );
  454.   STOP;
  455.  
  456. :LETTER_D
  457.   write( "Drop " );
  458.   L0 = select$n( player );
  459.   stats(-1);
  460.   if L0 >= 0 then
  461.     writeln( player.bp.name );
  462.     runscript( player.bp.script, "CURRITEM", DROP );
  463.     ! Does NOT return !
  464.   endif;
  465.   writeln( "nothing.." );
  466.   if L0 < -1 then
  467.     writeln( "You are not carrying anything!" );
  468.   endif;
  469.   STOP;
  470.  
  471. :LETTER_E
  472.   if group.vehicle.count then ! Must be on foot !
  473.     writeln( "You must be on foot to enter/exit worlds.." );
  474.     STOP;
  475.   endif;
  476.   if group.x <> 0 or group.y <> 0 then
  477.     for L0 = 0 to 31 do
  478.       if world.doorx(L0) = group.x and world.doory(L0) = group.y then
  479.         world.door = L0; ! Use this door !
  480.         writeln( "Please wait..." );
  481.         runscript( WORLD, "WORLDDEF", EXIT );
  482.         ! Should not return !
  483.       endif;
  484.     endfor;
  485.   endif;
  486.   writeln( "There is no door here.." );
  487.   STOP;
  488.  
  489. :LETTER_F
  490.   STOP;
  491.  
  492. :LETTER_G
  493.   ! Get !
  494.   if player.hp > 1 then
  495.     write( "Get " );
  496.     L0 = locate( object ); ! Find OBJECT only, no people !
  497.     if success then 
  498.       writeln( object.type );
  499.       if L0 < 2 then
  500.         runscript( object.script, "OBJECT", GET );
  501.         ! Does NOT return !
  502.       else
  503.         writeln( "You can't reach the ", object.type );
  504.       endif;
  505.     else
  506.       goto NOTHING;
  507.     endif;
  508.   else
  509.     write( player.name, " can't get anything.." );
  510.   endif;
  511.   STOP;
  512.  
  513. :LETTER_H  
  514.   STOP;
  515.  
  516. :LETTER_I
  517.   display$n( player );
  518.   STOP;
  519.  
  520. :LETTER_J
  521.   STOP;
  522.  
  523. :LETTER_K
  524.   STOP;
  525.  
  526. :LETTER_L
  527.   write( "Look at " );
  528.   L0 = locate; ! Find ANYTHING !
  529.   if success then 
  530.     if npc.count then ! Found an NPC !
  531.       writeln( npc.type );
  532.       runscript( npc.script, "OBJECT", LOOK );
  533.     endif;
  534.     writeln( object.type );
  535.     runscript( object.script, "OBJECT", LOOK );
  536.   endif;
  537.   goto NOTHING;
  538.  
  539. :LETTER_M
  540.   STOP;
  541.  
  542. :LETTER_N
  543.   write( "Invoke " );
  544.   L0 = select$n( player, SCROLL, GEMS );
  545.   stats(-1);
  546.   if L0 >= 0 then
  547.     runscript( player.bp.script, "CURRITEM", INVOKE );
  548.     ! Does NOT return !
  549.   endif;
  550.   writeln( "nothing .." );
  551.   if L0 < -1 then
  552.     writeln( "You have no items that you can invoke.." );
  553.   endif;
  554.   STOP;
  555.  
  556. :LETTER_O
  557.   STOP;
  558.  
  559. :LETTER_P
  560.   STOP;
  561.  
  562. :LETTER_Q
  563.   write( "Quaff (eat or drink) " );
  564.   L0 = select$n( player, FOOD, POTION );
  565.   stats(-1);
  566.   if L0 >= 0 then
  567.     runscript( player.bp.script, "CURRITEM", INVOKE );
  568.     ! Does NOT return !
  569.   endif;
  570.   writeln( "nothing .." );
  571.   if L0 < -1 then
  572.     writeln( "You have no items that you can eat or drink" );
  573.   endif;
  574.   STOP;
  575.  
  576. :LETTER_R
  577.   write( "Remove " );
  578.   L0 = select( player.body ); ! Any worn item !
  579.   stats(-1);
  580.   if L0 >= 0 then
  581.     runscript( player.body.script, "CURRITEM", REMOVE );
  582.   endif;
  583.   writeln( "nothing.." );
  584.   if L0 < -1 then
  585.     writeln( "You have no items to remove!" );
  586.   endif;
  587.   STOP;
  588.  
  589. :LETTER_S
  590.   runscript( player.script, "CASTING", CAST );
  591.   STOP;
  592.  
  593. :LETTER_T
  594.   write( "Talk to " );
  595.   L0 = locate; ! Find ANYTHING !
  596.   if success then 
  597.     if npc.count then ! Found an NPC !
  598.       if abs(npc.x - player.x) > 2 or abs(npc.y - player.y) > 2 then
  599.         writeln( "You must get closer!" );
  600.         STOP;
  601.       endif;
  602.       writeln( npc.type );
  603.       runscript( npc.script, "OBJECT", TALK );
  604.     endif;
  605.     if abs(object.x - player.x) > 2 or abs(object.y - player.y) > 2 then
  606.       writeln( "You must get closer!" );
  607.       STOP;
  608.     endif;
  609.     writeln( object.type );
  610.     runscript( object.script, "OBJECT", TALK );
  611.   endif;
  612.   if group.x = pointx and group.y = pointy then
  613.     writeln( "yourself..?" );
  614.   else
  615.     writeln( "no one.." );
  616.   endif;
  617.   STOP;
  618.  
  619. :LETTER_U
  620.   write( "Use " );
  621.   L0 = locate( OBJECT ); ! Find an object !
  622.   if success then 
  623.     if abs(object.x - player.x) > 2 or abs(object.y - player.y) > 2 then
  624.       writeln( "You must get closer!" );
  625.       STOP;
  626.     endif;
  627.     writeln( object.type );
  628.     runscript( object.script, "OBJECT", USE );
  629.   endif;
  630.   goto NOTHING;
  631.  
  632. :LETTER_V
  633.   if group.size > 1 then
  634.     writeln( "Who leaves the party?" );
  635.     L0 = select( group );
  636.     stats(-1);
  637.     if player.index = 0 then
  638.       writeln( "You can't leave the party!" );
  639.       STOP;
  640.     endif;
  641.     if player.hp = 0 then
  642.       writeln( "You leave ", player.name, "'s body to the vultures.." );
  643.     elsif player.hp < 2 then
  644.       writeln( "You abandon ", player.name, ", who is almost dead.." );
  645.     else
  646.       writeln( player.name, " leaves the group." );
  647.     endif;
  648.     LEAVE(player.index);
  649.     stats(-1);
  650.   else
  651.     writeln( "You are alone!" );
  652.   endif;
  653.   STOP;
  654.  
  655. :LETTER_W
  656.  
  657.   write( "Wear (or Wield) " );
  658.   L0 = select$n( player, WEAPON, ARMOR, RING, AMULET, STAFF );
  659.   stats(-1);
  660.   if L0 >= 0 then
  661.     runscript( player.bp.script, "CURRITEM", WEAR );
  662.     ! Does NOT return !
  663.   endif;
  664.   writeln( "nothing .." );
  665.   if L0 < -1 then
  666.     writeln( "You have no items that you can wear or wield" );
  667.   endif;
  668.   STOP;
  669.  
  670. :LETTER_X
  671.   if group.vehicle.count then
  672.     ! We are riding on a vehicle !
  673.     curritem = group.vehicle;
  674.     runscript( group.vehicle.script, "CURRITEM", EXIT );
  675.   else
  676.     writeln( "You are already on foot!" );
  677.   endif;
  678.   STOP;
  679.  
  680. :LETTER_Y
  681.   STOP;
  682.  
  683. :LETTER_Z
  684.   if player.staff.count then
  685.     curritem = player.staff;
  686.     runscript( player.staff.script, "CURRITEM", invoke );
  687.   endif;
  688.   STOP;
  689.  
  690. :NOTHING
  691.   if group.x = pointx and group.y = pointy then
  692.     writeln( "yourself..?" );
  693.   else
  694.     writeln( "nothing.." );
  695.   endif;
  696.   STOP;
  697.  
  698. :SPACE
  699.   writeln( "Pass.." );
  700.   goto @0; ! Time Control !
  701.  
  702. :VIEW_CLICK
  703.   ! Did we click on ourselves? !
  704.   if group.x = pointx and group.y = pointy then
  705.     writeln( "Don't do that! It tickles.." );
  706.     STOP;
  707.   endif;
  708.   ! First, check the objects !
  709.   L2 = locate( object, pointx, pointy );
  710.   if success then
  711.     if button = 1 then
  712.       if abs(pointx - player.x) > 1 or abs(pointy - player.y) > 1 then
  713.         writeln( "You can't reach the ", object.type );
  714.         STOP;
  715.       endif;
  716.       if object.type = VEHICLE or object.type = DOOR or
  717.          object.type = SIGN    or
  718.          object.type = CHEST and object.locktype > 0 then
  719.         writeln( "Use ", object.type );
  720.         runscript( object.script, "OBJECT", USE );
  721.       else
  722.         writeln( "Get ", object.type );
  723.         runscript( object.script, "OBJECT", GET );
  724.       endif;
  725.     elsif button = 2 then
  726.       writeln( "Look at ", object.type );
  727.       runscript( object.script, "OBJECT", LOOK );
  728.     else
  729.       writeln( "The middle button has no effect!" );
  730.       stop;
  731.     endif;
  732.   endif;
  733.   ! Next check the characters !
  734.   L2 = locate( npc, pointx, pointy );
  735.   if success then
  736.     if button = 1 then
  737.       if abs(pointx - player.x) > 2 or abs(pointy - player.y) > 2 then
  738.         writeln( "You must get nearer for conversation." );
  739.         STOP;
  740.       endif;
  741.       writeln( "Talk to ", npc.type );
  742.       runscript( npc.script, "OBJECT", TALK );
  743.     elsif button = 2 then
  744.       writeln( "Look at ", npc.type );
  745.       runscript( npc.script, "OBJECT", LOOK );
  746.     else
  747.       writeln( "The middle button has no effect!" );
  748.     endif;
  749.   endif;
  750.   STOP;
  751.  
  752. :MENU_CLICK
  753.   ! I don't do anything with this right now.. !
  754.   STOP;
  755.  
  756. :ICON_CLICK
  757.   on pointx goto
  758.     LETTER_A,  ! Attack !
  759.     LETTER_G,  ! Get !
  760.     LETTER_D,  ! Drop !
  761.     LETTER_L,  ! Look !
  762.     LETTER_T,  ! Talk !
  763.     LETTER_C,  ! Camp Out or Sleep !
  764.     LETTER_E,  ! Enter or Exit through a door !
  765.     LETTER_I;  ! INVENTORY !
  766.   STOP;
  767.  
  768. :STAT_CLICK
  769.   if pointx = 6 and pointy < group.size then
  770.     ! Looking at Group, selected an individual !
  771.     GROUP.CURRENT = pointy;
  772.     STATS( GROUP.CURRENT );        ! Display INDIVIDUAL statistics !
  773.   else
  774.     ! Looking at Individual (point x), clicked at item)
  775.     on pointy goto 
  776.       SHOW_GRP,    ! No item, so go back to showing the GROUP
  777.       SHOW_WPN,    ! Clicked at weapon being worn (or empty place)
  778.       SHOW_SHLD,   ! Clicked at shield being worn (or empty place)
  779.       SHOW_ARMR,   ! Clicked at armor being worn (or empty place)
  780.       SHOW_STF,    ! Clicked at staff being worn (or empty place)
  781.       SHOW_RING,   ! Clicked at ring being worn (or empty place)
  782.       SHOW_AMULET; ! Clicked at amulet being worn (or emtpy place)
  783.     ! No, Clicked at item in the back pack !
  784.     if pointy > 6 and pointy < 22 then
  785.       setbp( player, pointy - 7 );
  786.       gosub DO_BP_ITEM;
  787.     endif;
  788.   endif;
  789.   STOP;
  790.  
  791. :SHOW_GRP
  792.   stats(6); STOP;
  793.  
  794. :SHOW_WPN
  795.   if player.weapon.count then
  796.     curritem = player.weapon;
  797.     gosub DO_WORN_ITEM;
  798.   endif;
  799.   STOP;
  800.  
  801. :SHOW_SHLD
  802.   if player.shield.count then
  803.     curritem = player.shield;
  804.     gosub DO_WORN_ITEM;
  805.   endif;
  806.   STOP;
  807.  
  808. :SHOW_ARMR
  809.   if player.armor.count then
  810.     curritem = player.armor;
  811.     gosub DO_WORN_ITEM;
  812.   endif;
  813.   STOP;
  814.  
  815. :SHOW_STF
  816.   if player.staff.count then
  817.     curritem = player.staff;
  818.     gosub DO_WORN_ITEM;
  819.   endif;
  820.   STOP;
  821.  
  822. :SHOW_RING
  823.   if player.ring.count then
  824.     curritem = player.ring;
  825.     gosub DO_WORN_ITEM;
  826.   endif;
  827.   STOP;
  828.  
  829. :SHOW_AMULET
  830.   if player.amulet.count then
  831.     curritem = player.amulet;
  832.     gosub DO_WORN_ITEM;
  833.   endif;
  834.   STOP;
  835.  
  836. :DO_WORN_ITEM
  837.   if button = 1 then
  838.     writeln( "Remove ", curritem.type, ".." );
  839.     runscript( curritem.script, "CURRITEM", REMOVE );
  840.   elsif button = 2 then
  841.     writeln( "Look at ", curritem.type );
  842.     runscript( curritem.script, "CURRITEM", LOOK );
  843.   endif;
  844.   return;
  845.  
  846. :DO_BP_ITEM
  847.   if player.bp.count then
  848.     curritem = player.bp;
  849.     if button = 1 then
  850.       if curritem.type = WEAPON or curritem.type = ARMOR or
  851.          curritem.type = RING   or curritem.type = AMULET or
  852.          curritem.type = SHIELD or curritem.type = STAFF then
  853.          writeln( "Wear/Wield ", curritem.type, ".." );
  854.          runscript( curritem.script, "CURRITEM", WEAR );
  855.       else
  856.          writeln( "Use ", curritem.type, ".." );
  857.          runscript( curritem.script, "CURRITEM", USE );
  858.       endif;
  859.     elsif button = 2 then
  860.       writeln( "Look at ", curritem.type );
  861.       runscript( curritem.script, "CURRITEM", LOOK );
  862.     endif;
  863.   endif;
  864.   return;
  865.  
  866. !---------------------------------------------------------------------------!
  867. !---------------------------------------------------------------------------!
  868. !---------------------------------------------------------------------------!
  869. !---------------------------------------------------------------------------!
  870. !---------------------------------------------------------------------------!
  871. !
  872. ! SUBROUTINE: HEAL_HP
  873. !
  874. ! Heal the players with the passage of time
  875. !
  876. :HEAL_HP
  877.   ! alive and not sick !
  878.   if player.hp > 0 and not player.poisoned then
  879.     dec( player.energy );
  880.     if player.energy <= 0 then
  881.       if group.food > 0 then
  882.         dec( group.food );
  883.         player.energy = 255;
  884.       else
  885.         writeln( player.name, " goes hungry!" );
  886.         return;
  887.       endif;
  888.     endif;
  889.     if player.hp < player.mhp then
  890.       inc( player.hp );
  891.     endif;
  892.   endif;
  893.   return;
  894.  
  895. !
  896. ! SUBROUTINE: HEAL_PWR
  897. !
  898. ! Restore magic points withthe passage of time..
  899. !
  900. :HEAL_PWR
  901.   if player.hp > 0 and player.energy > 0 and player.pwr < player.mpwr then
  902.     inc( player.pwr );
  903.     if player.class = ELF and player.pwr < player.mpwr then
  904.       inc( player.pwr ); ! Do elves faster.. !
  905.     endif;
  906.   endif;
  907.   return;
  908.  
  909. !
  910. ! SUBROUTINE to create a Random Monster
  911. !
  912. :NEWMONSTER
  913.   ! Try to find a position for the monster up to 8 times..
  914.   for L3 = 1 to 8 do
  915.     L0 = group.x + random(8) - 4;
  916.     L1 = group.y + random(8) - 4;
  917.     if L0 < 0 then L0 = 0; endif;
  918.     if L1 < 0 then L1 = 0; endif;
  919.     if L0 >= world.x then L0 = world.x - 1; endif;
  920.     if L1 >= world.y then L1 = world.y - 1; endif;
  921.     if L0 <> player.x or L1 <> player.y then
  922.       L2 = world.density(L0,L1);
  923.       if L2 = FLAT or L2 = ROUGH or L2 = VERY_ROUGH or L2 = SWAMP or L2 = DESERT then
  924.         ! Create a LAND-BASED monster !
  925.         L2 = random(3);    ! Small, Medium or Large (0-2) !
  926.         L3 = random(L2+3); ! Select a graphics block for that size (0-4) !
  927.         if world.type = DUNGEON then
  928.           L4 = DEFCAVEBLK( L3 );            ! Leader   !
  929.           L5 = DEFCAVEBLK( random(L3+1) );  ! Follower !
  930.           L6 = CAVE_MONSTER;
  931.         elsif world.type = HAUNTED then
  932.           L4 = DEFSPOOKBLK( L3 );           ! Leader   !
  933.           L5 = DEFSPOOKBLK( random(L3+1) ); ! Follower !
  934.           L6 = SPOOK_MONSTER;
  935.         else
  936.           ! OUTDOORS or ARENA !
  937.           L4 = DEFLANDBLK( L3 );            ! Leader   !
  938.           L5 = DEFLANDBLK( random(L3+1) );  ! Follower !
  939.           L6 = LAND_MONSTER;
  940.         endif;
  941.         goto DOIT;
  942.       elsif L2 = DEEP_WATER then
  943.         ! Create a WATER-BOUND monster !
  944.         L2 = random(3);        ! Small, Medium, Large (0-2) !
  945.         if random(5) = 0 then  ! Pirate Ship (SPECIAL CASE) !
  946.           L4 = DEFWATERBLK(4); ! Fifth water monster is a ship !
  947.           L5 = DEFWATERBLK(4); ! Followers are ships also !
  948.         else
  949.           L3 = random(L2+2); ! Select a graphics block for that size (0-3) !
  950.           L4 = DEFWATERBLK( L3 );            ! Leader   !
  951.           L5 = DEFWATERBLK( random(L3+1) );  ! Follower !
  952.         endif;
  953.         L6 = WATER_MONSTER;
  954.         goto DOIT;
  955.       endif;
  956.     endif;
  957.   endfor;
  958.   return; ! Tried 8 Times, give up !
  959.  
  960. :DOIT
  961.   new(npc,L0,L1,L4);
  962.   npc.type   = HOSTILE;       ! NPC Type
  963.   npc.stats  = defstat(L2);   ! Statistics Record
  964.   npc.block2 = L5;            ! Followers (if any)
  965.   npc.class  = L6;            ! Monster Class
  966.  
  967.   ! Gold carried
  968.   if world.type = ARENA then
  969.     npc.value = random(50)+1; ! Very little money (Up to 5 gold pieces) !
  970.   else
  971.     npc.value = 0;
  972.   endif;
  973.  
  974.   !
  975.   ! # of monsters in the group.  The formula is based on L2 (monster size).
  976.   ! If small  (L2=0), then # = random( group.size + 6 ) + 1
  977.   ! If medium (L2=1), then # = random( group.size + 3 ) + 1
  978.   ! if large  (L2=2), then # = random( group.size ) + 1
  979.   npc.count = random( group.size + (2 - L2) * 3 ) + 1;
  980.  
  981.   L254 = TRUE; ! Monster has been created !
  982.  
  983.   voice( "ALERT", 1000 );
  984.   return;
  985.  
  986. !
  987. ! This SUBROUTINE will hit every player in the group by using the
  988. ! subroutine HITPLAYER.
  989. !
  990. :HITGROUP
  991.   foreach player do
  992.     gosub HITPLAYER;
  993.   endfor;
  994.   return;
  995.  
  996. !
  997. ! This SUBROUTINE will decrement the hit points of the current
  998. ! group member.  It checks to see if the player has died or lost
  999. ! consciousnes.  The variable S0 contains the reason for the hit.
  1000. !
  1001. :HITPLAYER
  1002.   if player.hp > 0 then
  1003.     dec( player.hp );
  1004.     if player.hp = 0 then
  1005.       writeln( player.name, " has died of ", s0, "!" );
  1006.     elsif player.hp = 1 then
  1007.       writeln( player.name, " has fainted from ", s0, "!" );
  1008.     else
  1009.       writeln( player.name, " weakens!" );
  1010.     endif;
  1011.   endif;
  1012.   return;
  1013.  
  1014. !------------------------------------------------------------------------!
  1015. !
  1016. ! SUBROUTINE: M1_INVOKE
  1017. !
  1018. ! Type 1 Magic - Affects the person invoking the magic..
  1019. !
  1020. ! This code is equivalent to the one in OBJECT.SCR.  When resting, 
  1021. ! rings and amulets that have magical properties will re-invoke their
  1022. ! effect when you wake up.
  1023. !
  1024. !------------------------------------------------------------------------!
  1025. :M1_INVOKE
  1026. !------------------------------------------------------------------------!
  1027.  
  1028.   if curritem.cursed then
  1029.     if curritem.permanent then
  1030.       writeln( "WARNING: Cursed Item with permanent effect not recommended!");
  1031.       curritem.permanent = FALSE;
  1032.     endif;
  1033.   endif;
  1034.  
  1035.   if curritem.charges < 255 then
  1036.     dec(curritem.charges);  ! 255 means forever !
  1037.   endif;
  1038.  
  1039.   on curritem.class goto
  1040.     M1_NONE,    M1_CURE,    M1_HEAL,    M1_POISON,    M1_RESTORE,
  1041.     M1_STR,     M1_DEX,     M1_SPD,     M1_AIM,       M1_AC,
  1042.     M1_HP,      M1_IQ,      M1_PWR;
  1043.  
  1044. :M1_NONE
  1045.   return;
  1046.  
  1047. :M1_CURE
  1048.   if player.poisoned then
  1049.     player.poisoned = 0;
  1050.     writeln( player.name, " is now cured." );
  1051.   endif;
  1052.   return;
  1053.  
  1054. :M1_HEAL
  1055.   if player.hp > 0 and player.hp < player.mhp then
  1056.     if curritem.units > 0 then
  1057.       L(0) = curritem.units;                   ! always heals the same points !
  1058.     else
  1059.       L(0) = random(player.mhp - player.hp)+1; ! heal a random number of points !
  1060.     endif;
  1061.     if player.hp + L(0) < player.mhp then
  1062.       writeln( player.name, " heals ", L(0), " hit points.." );
  1063.       inc( player.hp, L(0) );
  1064.     else
  1065.       writeln( player.name, " has been completely healed!" );
  1066.       player.hp = player.mhp;
  1067.     endif;
  1068.   endif;
  1069.   return;
  1070.  
  1071. :M1_POISON
  1072.   if NOT player.poisoned then
  1073.     player.poisoned = TRUE;
  1074.     writeln( player.name, " is poisoned!" );
  1075.   endif;
  1076.   return;
  1077.  
  1078. :M1_RESTORE
  1079.   if player.hp < player.mhp then
  1080.     player.hp = player.mhp;
  1081.     writeln( player.name, " is completely healed!" );
  1082.   endif;
  1083.   return;
  1084.  
  1085. :M1_STR
  1086.   if curritem.cursed then
  1087.     player.str = 0;
  1088.   else
  1089.     inc( player.str, curritem.units );
  1090.     if curritem.permanent then
  1091.       inc( player.mstr, curritem.units );
  1092.     endif;
  1093.     writeln( player.name, "'s strength increased by ", curritem.units, "!" );
  1094.   endif;
  1095.   return;
  1096.  
  1097. :M1_DEX
  1098.   if curritem.cursed then
  1099.     player.dex = 0;
  1100.   else
  1101.     inc( player.dex, curritem.units );
  1102.     if curritem.permanent then
  1103.       inc( player.mdex, curritem.units );
  1104.     endif;
  1105.     writeln( player.name, "'s dexterity increased by ", curritem.units, "!" );
  1106.   endif;
  1107.   return;
  1108.  
  1109. :M1_SPD
  1110.   if curritem.cursed then
  1111.     player.spd = 0;
  1112.   else
  1113.     inc( player.spd, curritem.units );
  1114.     if curritem.permanent then
  1115.       inc( player.mspd, curritem.units );
  1116.     endif;
  1117.     writeln( player.name, "'s speed increased by ", curritem.units, "!" );
  1118.   endif;
  1119.   return;
  1120.  
  1121. :M1_AIM
  1122.   if curritem.cursed then
  1123.     player.aim = 0;
  1124.   else
  1125.     inc( player.aim, curritem.units );
  1126.     if curritem.permanent then
  1127.       inc( player.maim, curritem.units );
  1128.     endif;
  1129.     writeln( player.name, "'s aim increased by ", curritem.units, "!" );
  1130.   endif;
  1131.   return;
  1132.  
  1133. :M1_AC
  1134.   if curritem.cursed then
  1135.     player.ac = 0;
  1136.   else
  1137.     inc( player.ac, curritem.units );
  1138.     if curritem.permanent then
  1139.       inc( player.mac, curritem.units );
  1140.     endif;
  1141.     writeln( player.name, "'s armor class increased by ", curritem.units, "!" );
  1142.   endif;
  1143.   return;
  1144.  
  1145. :M1_HP
  1146.   if curritem.cursed then
  1147.     player.hp = player.hp / 3 + 1;
  1148.   else
  1149.     inc( player.hp, curritem.units );
  1150.     if curritem.permanent then
  1151.       inc( player.mhp, curritem.units );
  1152.     endif;
  1153.     writeln( player.name, "'s hit points increased by ", curritem.units, "!" );
  1154.   endif;
  1155.   return;
  1156.  
  1157. :M1_IQ
  1158.   if curritem.cursed then
  1159.     player.iq = 0;
  1160.   else
  1161.     inc( player.iq, curritem.units );
  1162.     if curritem.permanent then
  1163.       inc( player.miq, curritem.units );
  1164.     endif;
  1165.     writeln( player.name, "'s i.q. increased by ", curritem.units, "!" );
  1166.   endif;
  1167.   return;
  1168.  
  1169. :M1_PWR
  1170.   if player.class = ELF or player.class = WIZARD then
  1171.     if curritem.cursed then
  1172.       player.pwr = 0;
  1173.     else
  1174.       inc( player.pwr, curritem.units );
  1175.       if curritem.permanent then
  1176.         inc( player.mpwr, curritem.units );
  1177.       endif;
  1178.       writeln( player.name, "'s power increased by ", curritem.units, "!" );
  1179.     endif;
  1180.   else
  1181.     write( player.name, " has a headache all night long.." );
  1182.     if player.hp < 3 then
  1183.       writeln( " and dies!" );
  1184.       player.hp = 0;
  1185.     else
  1186.       writeln;
  1187.       dec( player.hp, 2 );
  1188.     endif;
  1189.   endif;
  1190.   return;
  1191.  
  1192. !-----------------------------------------------------------------------!
  1193. :CLOCK_TICK
  1194. !-----------------------------------------------------------------------!
  1195. ! Allow one minute to go by
  1196.  
  1197.   if minute < MinutesInAnHour - 1 then
  1198.     inc( minute );
  1199.   else
  1200.     minute = 0;
  1201.     if hour < HoursInADay - 1 then
  1202.       inc( hour );
  1203.     else
  1204.       hour = 0;
  1205.       if day < DaysInAMonth - 1 then
  1206.         inc( day );
  1207.       else
  1208.         day = 0;
  1209.         if month < MonthsInAYear - 1 then
  1210.           inc( month );
  1211.         else
  1212.           month = 0;
  1213.           inc( year );
  1214.         endif;
  1215.       endif;
  1216.     endif;
  1217.   endif;
  1218.   return;
  1219.  
  1220. !------------------------------------------------------
  1221. ! Attack an NPC
  1222. !------------------------------------------------------
  1223.  
  1224. :ATTACK_NPC
  1225.   ! L3 contains distance to current npc per LOCATE command !
  1226.   ! L4 the weapon class (blunt, missile, etc)
  1227.   ! L5 the range (distance) you can reach with this weapon
  1228.   ! L6 is non-zero if type of ammo that is needed by the weapon
  1229.   ! L7 is the damage points done
  1230.   if player.weapon.count then 
  1231.     L4 = player.weapon.class;
  1232.     L5 = player.weapon.range;
  1233.     L6 = player.weapon.ammoneeded;
  1234.     L7 = player.weapon.damage;
  1235.   else
  1236.     L4 = BLUNT;
  1237.     L5 = 1;
  1238.     L6 = 0;
  1239.     L7 = 1;
  1240.   endif;
  1241.   if L4 = MISSILE then
  1242.     for L10 = 0 to 15 do
  1243.       setbp( player, L10 );
  1244.       if player.bp.count then
  1245.         if player.bp.type = AMMO and player.bp.ammotype = L6 then
  1246.           if player.bp.count < 255 then
  1247.             dec(player.bp.count);          ! Count of 255 means it never ends? !
  1248.           endif;
  1249.           L5 = max( L5, player.bp.range ); ! Use ammo's range if higher !
  1250.           inc( L7, player.bp.damage );     ! If ammunition causes extra damage !
  1251.           L6 = L10;                        ! Keep AMMO's BP here !
  1252.           goto FOUND_AMMO;
  1253.         endif;
  1254.       endif;
  1255.     endfor;
  1256.     writeln( "Out of ammo! Using hands!" );
  1257.     L4 = BLUNT;
  1258.     L5 = 1;
  1259.     L6 = 0;
  1260.     L7 = 1;
  1261. :FOUND_AMMO
  1262.   endif;
  1263.   if L5 < L3 then
  1264.     writeln( "You have to get closer!" );
  1265.     stop;
  1266.   endif;
  1267.  
  1268.   ! HERE I COULD 'RANDOMIZE' THE DAMAGE, BUT I'LL LET IT BE CONSTANT FOR NOW !
  1269.  
  1270.   ! For contact weapons, STRENGTH increases damage !
  1271.   if L4 = BLUNT or L4 = EDGED then
  1272.     inc( L7, adjustments( player.str ) );
  1273.   endif;
  1274.  
  1275.   ! Now, we have to figure out if we missed !
  1276.   if L4 = MISSILE then
  1277.     ! For missile weapon, hit 5 out of 10, adjusted by AIM !
  1278.     if random( 10 ) + adjustments( player.aim ) < 5 then
  1279.       writeln( player.name, " missed.." );
  1280.       voice( "BadAim", 1000 );
  1281.     else
  1282.       gosub HIT_NPC;
  1283.     endif;
  1284.   else
  1285.     ! For non-missile weapon, hit 7 out of 10 adjusted up by the
  1286.     ! player's dexterity and down by the NPC's dexterity
  1287.     if random(10) + adjustments(player.dex) - adjustments(npc.dex) < 3 then
  1288.       writeln( player.name, " missed.." );
  1289.       voice( "Swish", 1000 );
  1290.     else
  1291.       gosub HIT_NPC;
  1292.     endif;
  1293.   endif;
  1294.   stop;
  1295.  
  1296. :HIT_NPC
  1297.  
  1298.   L7 = max( L7, 1 ); ! At least one HP of damage !
  1299.   if npc.hp > 1 and npc.ac > 0 then ! Armor Class protects the NPC !
  1300.     L8 = random( npc.ac+1 ); ! Absorb 0 to npc.ac damage points !
  1301.     if L8 >= L7 then
  1302.       writeln( npc.type, "'s armor absorbs the impact!" );
  1303.       voice( "Clank", 1000 );
  1304.       return;
  1305.     endif;
  1306.     dec( L7, L8 ); ! Reduce damage by L8 amount !
  1307.   endif;
  1308.  
  1309.   ! Fast PLAYERS get to hit more than once !
  1310.   if player.spd > npc.spd then
  1311.     L9 = (player.spd - npc.spd) / 10 + 1;
  1312.   else 
  1313.     L9 = 1;
  1314.   endif;
  1315.   while L9 > 0 and npc.count do
  1316.     if npc.hp > L7 then
  1317.       write( npc.type, " hit!" );
  1318.       dec( npc.hp, L7 );
  1319.       on random(3) gosub :V1, :V2, :V3;
  1320.     else
  1321.       write( npc.type, " killed!" );
  1322.       voice( "YouKill", 1000 );
  1323.       L7 = npc.hp;
  1324.       ! Now is the perfect time to GENERATE RANDOM TREASURE !
  1325.       gosub TREASURE;
  1326.       npc.count = 0; ! Actually Kill the NPC !
  1327.     endif;
  1328.     writeln( " (", L7, " points)" );
  1329.     inc( player.exp, L7 ); 
  1330.     dec(L9);
  1331.   endwhile;
  1332.  
  1333.   return;
  1334.  
  1335. :V1 voice( "Argh",   1000 ); return;
  1336. :V2 voice( "Ouch",   1000 ); return;
  1337. :V3 voice( "Whoosh", 1000 ); return;
  1338.  
  1339. !------------------------------------
  1340. :TREASURE
  1341. !------------------------------------
  1342. ! Generate random treasure
  1343.  
  1344.   ! First, leave the contents of the NPCs backpack..
  1345.   foreach npc.bp do
  1346.     drop( npc.bp, -npc.count, npc.x, npc.y ); ! Drop a copy of this item
  1347.   endfor;
  1348.  
  1349.   ! Now generate a random treasure
  1350.   on random(4) goto GT_NONE, GT_GOLD, GT_CHEST, GT_SPECIAL;
  1351. :GT_NONE
  1352.   return;
  1353.  
  1354. :GT_GOLD
  1355.   new( object, npc.x, npc.y, GOLDSACK );
  1356.   object.weight = random( player.mhp ) + 1;
  1357.   object.value  = object.weight * 10;
  1358.   return;
  1359.  
  1360. :GT_CHEST
  1361.   new( object, npc.x, npc.y, CHEST );
  1362.   object.class  = NORMAL_CHEST;
  1363.   object.weight = random( player.mhp ) + 1;
  1364.   object.value  = object.weight * 10;
  1365.   object.locktype = random(2); ! 0=None, 1+ = Key !
  1366.   object.traptype = random(3); ! 0=None, 1=Poison, 2+ = Bomb !
  1367.   return;
  1368.  
  1369. :GT_SPECIAL
  1370.   ! AMULET=5,RING=6,POTION=7,SCROLL=8,STAFF=9
  1371.   new( object, npc.x, npc.y, AMULET + random(5) );
  1372.   if object.type = SCROLL or object.type = STAFF then ! SCROLL or STAFF !
  1373.     object.class  = random(15)+1; ! See OBJECT CLASS in DCCTOKEN.DAT !
  1374.   else
  1375.     object.class  = random(12)+1; ! See OBJECT CLASS in DCCTOKEN.DAT !
  1376.   endif;
  1377.   object.weight = 1;
  1378.   if object.type = RING or object.type = AMULET or object.type = STAFF then
  1379.     object.charges = random( player.level ) + 1;
  1380.   endif;
  1381.   if object.type = RING or object.type = AMULET or object.type = POTION then
  1382.     object.units  = random( player.mhp ) + 1;
  1383.     object.permanent = (random(100) = 0); ! One out of 100 !
  1384.   endif;
  1385.   if object.permanent then
  1386.     object.value  = 1000;
  1387.     object.weight =    2;
  1388.   else
  1389.     object.value =   10;
  1390.   endif;
  1391.   return;
  1392.  
  1393. !------------------------------------
  1394. :NEW_LEVEL
  1395. !------------------------------------
  1396.  
  1397.   L10 =   1;  ! Start with level 1
  1398.   L11 = 200;  ! Next level is at 200 
  1399.   while L11 < player.exp do
  1400.     inc( L11, L11 ); ! Each level is TWICE as much as the previous one !
  1401.     inc( L10, 1 );
  1402.   endwhile;
  1403.   if L10 > player.level then    ! New Level !
  1404.     L12 = random( player.level ) + 1;  ! First, give some hit points !
  1405.     write( "New level! ", player.name, " gained ", L12, "hp " );
  1406.     inc( player.level );
  1407.     inc( player.mhp, L12 );     ! Permanent Increase !
  1408.     inc( player.hp, L12 );      ! Reflect the new HP immediatly !
  1409.  
  1410.     ! Now increase one ore more attributes depending on the class !
  1411.     L12 = random(player.level + 1) + 1; ! Start with this many points !
  1412.     if L12 > 5 then
  1413.       L12 = random(10); ! Make more than 5 points 'unlikely' but possible
  1414.     endif;
  1415.     on player.class goto
  1416.       :EX_HUMAN,
  1417.       :EX_ELF,
  1418.       :EX_DWARF,
  1419.       :EX_WIZARD,
  1420.       :EX_ARCHER,
  1421.       :EX_FIGHTER;
  1422.   endif;
  1423.   return; ! No new level !
  1424.  
  1425. :EX_HUMAN  ! Humans and 'unknown'
  1426.     inc( player.mstr, L12 );
  1427.     writeln( "and ", L12, " str." );
  1428.     return;
  1429.  
  1430. :EX_ELF
  1431.     inc( player.miq, L12 + L12 ); ! Elf gains intelligence twice as fast !
  1432.     writeln( "and ", L12, " iq." );
  1433.     return;
  1434.  
  1435. :EX_DWARF
  1436.     L13 = random(L12);
  1437.     inc( player.mstr, L12 - L13 ); ! Dwarf gains some strength !
  1438.     inc( player.mdex, L13 );       ! and some dexterity        !
  1439.     writeln( ", ", L12 - L13, " str and ", L13, " dex." );
  1440.     return;
  1441.  
  1442. :EX_WIZARD
  1443.     inc( player.miq, L12 ); ! Wizards gain intelligence !
  1444.     writeln( "and ", L12, " iq." );
  1445.     return;
  1446.  
  1447. :EX_ARCHER
  1448.     L13 = random(L12);
  1449.     inc( player.maim, L12 - L13 ); ! Dwarf gains some aim !
  1450.     inc( player.mspd, L13 );       ! and some speed       !
  1451.     writeln( ", ", L12 - L13, " aim and ", L13, " speed." );
  1452.     return;
  1453.  
  1454. :EX_FIGHTER
  1455.     inc( L12, random(L12) );       ! Fighters gain strength more quickly !
  1456.     inc( player.mstr, L12 );
  1457.     writeln( "and ", L12, " str." );
  1458.     return;
  1459.  
  1460. !
  1461. ! Look at current bp object
  1462. !
  1463. :DESCRIBE
  1464.   if curritem.picture >= 0 then
  1465.     viewpcx( curritem );
  1466.     if success then
  1467.       pause;
  1468.     endif;
  1469.     paint(window); ! Assumes the picture fits in the window !
  1470.   elsif curritem.type = SIGN or curritem.type = BOOK then
  1471.     readtext( curritem.text );
  1472.     RETURN;
  1473.   endif;
  1474.   write( "You see a ", curritem.name );
  1475.   write( ", Type: ", curritem.type );
  1476. !
  1477. ! The following is a 'cascading if..then..elsif..elsif.....else..endif' 
  1478. ! statement.  It is used here to illustrate it's usefulness.  The same
  1479. ! code could have been written with a 'ON object.type GOTO' statement.
  1480. !
  1481.   if object.type = FOOD or object.type = POTION  then
  1482.     if object.class then
  1483.       write( ", Class: ", object.class );
  1484.       if object.class <> CURE then
  1485.         write( ", Units: ", object.units );
  1486.       endif;
  1487.     endif;
  1488.   elsif object.type = WEAPON then
  1489.     write( ", Class: ", object.class, 
  1490.            ", Hands: ", object.hands, 
  1491.            ", Range: ", object.range, 
  1492.            ", Damage: ", object.damage );
  1493.     if object.ammoneeded then
  1494.       write( ", Needs ammo type: ", object.ammo_type );
  1495.     endif;
  1496.   elsif object.type = AMMO then
  1497.     write( ", Ammo Type: ", object.ammotype );
  1498.     if object.traptype then
  1499.       write( ", Poisoned" );
  1500.     endif;
  1501.     if object.damage then
  1502.       write( ", Extra Damage: ", object.damage );
  1503.     endif;
  1504.   elsif object.type = ARMOR or object.type = SHIELD then
  1505.     write( ", Armor Class: ", object.ac );
  1506.     if object.cursed then
  1507.       write( " Cursed!" );
  1508.     endif;
  1509.   elsif object.type = AMULET or object.type = RING or object.type = GEMS then
  1510.     if object.class then
  1511.       write( ", Class: ", object.class );
  1512.       write( ", Charges: ", object.charges );
  1513.       if object.class <> CURE then
  1514.         write( ", Units: ", object.units );
  1515.         if object.permanent then
  1516.           write( ", Permanent!" );
  1517.         else
  1518.           write( ", Temporary" );
  1519.         endif;
  1520.       endif;
  1521.       if object.cursed then
  1522.         write( ", Cursed!" );
  1523.       endif;
  1524.     endif;
  1525.   elsif object.type = SCROLL then
  1526.     write( ", Class: ", object.class );
  1527.   elsif object.type = STAFF then
  1528.     write( ", Class: ", object.class, ", Charges: ", object.charges );
  1529.   elsif object.type = CHEST then
  1530.     if object.locktype then
  1531.       write( ", Locked!" );
  1532.       if object.traptype = 0 then
  1533.         write( ", no traps" );
  1534.       elsif object.traptype = 1 then
  1535.         write( ", poison trap" );
  1536.       else
  1537.         write( ", bomb damage: ", object.traptype );
  1538.       endif;
  1539.     endif;
  1540. ! elsif object.type = KEYS     then
  1541. !   nothing special about it
  1542. ! elsif object.type = BOOK     then
  1543. !   nothing special about it
  1544. ! elsif object.type = GOLDSACK then
  1545. !   nothing special about it
  1546. ! elsif object.type = TORCH    then
  1547. !   nothing special about it
  1548. ! elsif object.type = LANTERN  then
  1549. !   nothing special about it
  1550. ! elsif object.type = ROPE     then
  1551. !   nothing special about it
  1552. ! elsif object.type = HOOKS    then
  1553. !   nothing special about it
  1554. ! elsif object.type = MIRROR   then
  1555. !   nothing special about it
  1556. ! elsif object.type = SIGN     then
  1557. !   nothing special about it
  1558.   elsif object.type = VEHICLE then
  1559.     write( ", Class: ", object.class );
  1560. ! else
  1561. !   user defined type?
  1562.   endif;
  1563.   if object.weight > 1 and object.weight < 256 then
  1564.     write( ", Weight: ", object.weight );
  1565.   endif;
  1566.   writeln( "." );
  1567.   return;
  1568.  
  1569. !
  1570. ! MOVING THE CHARACTERS
  1571. !
  1572.  
  1573. :MOVE_UP
  1574.   L3 =  0; L4 = -1; goto DO_MOVE;
  1575.  
  1576. :MOVE_DN
  1577.   L3 =  0; L4 =  1; goto DO_MOVE;
  1578.  
  1579. :MOVE_LF
  1580.   L3 = -1; L4 =  0; goto DO_MOVE;
  1581.  
  1582. :MOVE_RT
  1583.   L3 =  1; L4 =  0; goto DO_MOVE;
  1584.  
  1585. :MOVE_UL
  1586.   L3 = -1; L4 = -1; goto DO_MOVE;
  1587.     
  1588. :MOVE_DL
  1589.   L3 = -1; L4 =  1; goto DO_MOVE;
  1590.  
  1591. :MOVE_UR
  1592.   L3 =  1; L4 = -1; goto DO_MOVE;
  1593.  
  1594. :MOVE_DR
  1595.   L3 =  1; L4 =  1; goto DO_MOVE;
  1596.  
  1597. :DO_MOVE
  1598.   L0 = player.x + L3;
  1599.   L1 = player.y + L4;
  1600.   if world.wrap_around then
  1601.     if L0 < 0 then
  1602.       gosub NOTFIGHTING;
  1603.       L0 = world.x - 1;
  1604.     elsif L0 >= world.x then
  1605.       gosub NOTFIGHTING;
  1606.       L0 = 0;
  1607.     endif;
  1608.     if L1 < 0 then
  1609.       gosub NOTFIGHTING;
  1610.       L1 = world.y - 1;
  1611.     elsif L1 >= world.y then
  1612.       gosub NOTFIGHTING;
  1613.       L1 = 0;
  1614.     endif;
  1615.   else
  1616.     if L0 < 0 or L0 >= world.x or L1 < 0 or L1 >= world.y then
  1617.       gosub NOTFIGHTING;
  1618.       writeln( "Do you wan't to leave ", world.name, "?" );
  1619.       if select( "Yes", "No" ) = 0 then
  1620.         world.door = world.edge_door;
  1621.         runscript( WORLD, "WORLDDEF", EXIT );
  1622.         ! 
  1623.         ! NOTE: We could just run "enter( world.edge_door );" instead
  1624.         ! of the above two lines.  The difference is that when you
  1625.         ! run ENTER( door ), the driver does NOT call the @EXIT
  1626.         ! routine in the current world.  A minor but important
  1627.         ! difference. The reason for this, is that the behaviour of
  1628.         ! ENTERING A WORLD (i.e. load the world, call script at @GET,
  1629.         ! call script at @ENTER) is a feature of the driver, but
  1630.         ! the @EXIT entry point is handled entirely by the scripts
  1631.         ! themselves. If you don't want to take any action when you
  1632.         ! exit a world, you can change the above two lines to a 
  1633.         ! simple call to the ENTER() function.
  1634.         !
  1635.       endif;
  1636.       stats(-1);
  1637.       STOP; 
  1638.     endif;
  1639.   endif;
  1640.   !
  1641.   ! Use a LOOP through all the NPCs, to see if there is one
  1642.   ! standing at that spot or a guard NEAR the spot
  1643.   !
  1644.   L2 = locate( npc, L0, L1 ); ! Is there an object at L0,L1? !
  1645.   if L2 >= 0 then
  1646.     writeln( "There is someone standing in your way!" );
  1647.     STOP;
  1648.   endif;
  1649.   ! Check for guards !
  1650.   ! The following loop works fine, but it selects every NPC in the 
  1651.   ! world, loading it's statistics record into memory and causing
  1652.   ! a disk access. While the game driver has a small cache of stat
  1653.   ! records, it still is better to avoid a 'foreach' loop on the
  1654.   ! NPCs in the control script. Note that you can use foreach on
  1655.   ! the players and objects because they are already in memory.
  1656.   ! -> THIS WORKS, BUT CAUSES UNNECESARY DISK ACCESS
  1657.   !   foreach NPC do
  1658.   !     if npc.type = GUARD then
  1659.   !       if abs(npc.x - L0) < 2 and abs(npc.y - L1) < 2 then
  1660.   !         writeln( "There is a GUARD there!" );
  1661.   !         STOP;
  1662.   !       endif;
  1663.   !     endif;
  1664.   !   endfor;
  1665.   ! The following is better. It uses a new feature of the LOCATE
  1666.   ! command. If you provide an X,Y coordinate, it looks for the
  1667.   ! specified NPC or OBJECT at the given location. It only causes
  1668.   ! a disk access if there is an NPC at that location, and that
  1669.   ! NPC has a much better chance of having it's record cached.
  1670.   ! -> MUCH BETTER:
  1671.     if L3 then ! Moving on X !
  1672.       L2 = locate( npc, L0+L3, L1 );
  1673.       if success then gosub check_guard; endif;
  1674.       L2 = locate( npc, L0+L3, L1+1 );
  1675.       if success then gosub check_guard; endif;
  1676.       L2 = locate( npc, L0+L3, L1-1 );
  1677.       if success then gosub check_guard; endif;
  1678.     endif;
  1679.     if L4 then ! Moving on Y !
  1680.       L2 = locate( npc, L0  , L1+L4 );
  1681.       if success then gosub check_guard; endif;
  1682.       L2 = locate( npc, L0+1, L1+L4 );
  1683.       if success then gosub check_guard; endif;
  1684.       L2 = locate( npc, L0-1, L1+L4 );
  1685.       if success then gosub check_guard; endif;
  1686.     endif;
  1687.   !
  1688.   ! No find if there are any OBJECTS at the X, Y location.
  1689.   !
  1690.   L2 = locate( object, L0, L1 ); ! Is there an object at L0,L1? !
  1691.   if L2 >= 0 then
  1692.     ! Check for locked doors
  1693.     if object.type = DOOR and object.locktype > 0 then
  1694.       writeln("The door is locked!" );
  1695.       STOP;
  1696.     endif;
  1697.     ! Check for fences and things, both of which we should not
  1698.     ! be able to walk over.
  1699.     if object.type = FENCE or object.type = THING then
  1700.       writeln( "There is a ", object.name, " in your way" );
  1701.       STOP;
  1702.     endif;
  1703.   endif;
  1704.   !
  1705.   ! Now check the world's density and see if we can walk over it
  1706.   ! considering the type of landscape and the vehicle (if any)
  1707.   !
  1708.   L2 = world.density(L0,L1);
  1709.   if L2 = WALL or L2 = LOCKED_DOOR or L2 = HIDDEN_DOOR then
  1710.     STOP;   ! Can't Move !
  1711.   endif;
  1712.   on group.vehicle.class goto
  1713.     CHK_WALK, CHK_MOUNT, CHK_ATV, CHK_LFLY, CHK_MFLY, CHK_HFLY, CHK_RAFT, CHK_BOAT;
  1714.   ! Anything else, don't allow the move !
  1715.   STOP;
  1716. ! -- ON WATER -- !
  1717. :CHK_RAFT
  1718.   if L2 = LOW_WATER or L2 = ROUGH_WATER goto CHK_OK;
  1719.   STOP;
  1720. :CHK_BOAT
  1721.   if L2 = DEEP_WATER goto CHK_OK;
  1722.   STOP;
  1723. ! -- BY AIR -- !
  1724. :CHK_LFLY
  1725.   if L2 = DEEP_WATER then STOP; endif;
  1726.   ! Drop Through !
  1727. :CHK_MFLY
  1728.   if L2 = VERY_HIGH  then STOP; endif;
  1729.   ! Drop Through !
  1730. :CHK_HFLY
  1731.   goto CHK_OK;
  1732. :CHK_WALK
  1733.   if L2 = FLAT or L2 = DESERT or L2 = SWAMP goto CHK_OK;
  1734.   if L2 = ROUGH      and random(3) <> 0 or
  1735.      L2 = VERY_ROUGH and random(3)  = 0     goto CHK_OK;
  1736.   if L2 = ROUGH or L2 = VERY_ROUGH then
  1737.     writeln( "Rough terrain.." );
  1738.   endif;
  1739.   ! Anything else, don't allow the move !
  1740.   STOP;
  1741. :CHK_MOUNT
  1742.   if L2 = FLAT                          or
  1743.      L2 = ROUGH                         or
  1744.      L2 = VERY_ROUGH and random(3) <> 0 then ! 2 out of 3 ! 
  1745.     goto CHK_OK;
  1746.   endif;
  1747.   if L2 = VERY_ROUGH then
  1748.     writeln( "Very rough terrain.." );
  1749.   endif;
  1750.   STOP;
  1751. :CHK_ATV
  1752.   if L2 = FLAT or L2 = ROUGH or L2 = VERY_ROUGH or L2 = LOW_WATER then
  1753.     goto CHK_OK; ! All Terrain Vehicle !
  1754.   endif;
  1755.   ! Anything else, don't allow the move !
  1756.   STOP;
  1757.  
  1758. :CHECK_GUARD
  1759.   !
  1760.   ! From GUARD.SCR, npc.v1 = 1 means you have given the password to the
  1761.   ! guard, so you can pass.  npc.v1 = 2 means you have given a BRIBE to
  1762.   ! the guard, so you can also pass.
  1763.   !
  1764.   if npc.type = GUARD and npc.v1 = 0 then
  1765. writeln( "npc.name=",npc.name,", npc.v0=",npc.v0," npc.v1=",npc.v1);
  1766.     writeln( "There is a GUARD there!" );
  1767.     STOP;
  1768.   endif;
  1769.   return;
  1770. :CHK_OK
  1771.   ! Go Ahead and Move
  1772.   if fighting then
  1773.     if group.vehicle.count then ! Inside a vehicle !
  1774.       group.x = L0; group.y = L1;
  1775.     else
  1776.       player.x = L0; player.y = L1;
  1777.     endif;
  1778.   else
  1779.     group.x  = L0; group.y  = L1;
  1780.     ! Check for Trap doors !
  1781.     if L0 > 0 and L1 > 0 then
  1782.       for L5 = 0 to 31 do
  1783.         if L0 = world.doorx(L5) and L1 = world.doory(L5) then
  1784.           if world.trapdoorswitch(L5) then
  1785.             world.door = L5; ! Use this door !
  1786.             runscript( WORLD, "WORLDDEF", EXIT );
  1787.           endif;
  1788.         endif;
  1789.       endfor;
  1790.     endif;
  1791.   endif;
  1792.   STOP;
  1793.  
  1794. :NOTFIGHTING
  1795.   if fighting then
  1796.     writeln( "You can't leave during a fight.." );
  1797.     stop;
  1798.   endif;
  1799.   return;
  1800.  
  1801. :FKEY1
  1802. ! Help !
  1803.   writeln( "The following commands are defined:" );
  1804.   write( "A)ttack, ");
  1805.   write( "C)amp, ");
  1806.   write( "D)rop, ");
  1807.   write( "E)nter, ");
  1808.   write( "G)et, ");
  1809.   write( "I)nventory, ");
  1810.   write( "L)ook, ");
  1811.   write( "iN)voike, ");
  1812.   write( "Q)uaff (eat or drink), ");
  1813.   write( "R)emove, ");
  1814.   write( "S)pell, ");
  1815.   write( "T)alk, ");
  1816.   write( "U)se, ");
  1817.   write( "V)acate, ");
  1818.   write( "W)ield/Wear, ");
  1819.   write( "eX)it, ");
  1820.   write( "Z)ap (with staff),");
  1821.   write( "F1=Help, ", "F2=Save, ", "F3=Sound, ", "F4=Restore, ",
  1822.          "F6=Restart, ", "F10=Exit" );
  1823.   writeln;
  1824.   STOP;
  1825.  
  1826. :FKEY2
  1827.   L0 = getnum( "Save in what slot?", 0, 999 );
  1828.   if L0 >= 0 then
  1829.     save( L0 );
  1830.     stop;
  1831.   endif;
  1832.   continue;
  1833.  
  1834. :FKEY3
  1835.   sound = not sound;
  1836.   if sound then
  1837.     writeln( "Sound is now on!" );
  1838.   else
  1839.     writeln( "Sound is now off!" );
  1840.   endif;
  1841.   stop;
  1842.  
  1843. :FKEY4
  1844.   L0 = getnum( "Restore from what slot?", 1, 999 );
  1845.   if L0 > 0 then
  1846.     restore( L0 );
  1847.     writeln( "RESTORE OF SLOT ", L0, " FAILED!" );
  1848.   endif;
  1849.   stop;
  1850.  
  1851. :FKEY5
  1852.   stop;
  1853.  
  1854. :FKEY6
  1855.   writeln( "Do you really want to RESTART?" );
  1856.   L0 = select( "Yes", "No" );
  1857.   if L0 = 0 then
  1858.     restart;
  1859.     writeln( "RESTART FAILED!" );
  1860.   endif;
  1861.   stats(-1);
  1862.   stop;
  1863.  
  1864. :FKEY7
  1865.   foreach player do
  1866.     player.level = 10;
  1867.   endfor;
  1868.   stop;
  1869.  
  1870. :FKEY8
  1871.   savepcx( "SAVESCRN.PCX" );
  1872.   stop;
  1873.  
  1874. :FKEY9
  1875.   stop;
  1876.  
  1877. :FKEY10
  1878.   if fighting then
  1879.     writeln( "Press ESCape to stop the fight, then F10 to exit!" );
  1880.     stop;
  1881.   endif;
  1882.   writeln( "See you later..." );
  1883.   save(0);
  1884.   end_game;
  1885.  
  1886.